package com.kusen.aqs;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 前提：这些源码类的东西，是要长期的复习总结去发现新的东西。尝试自己去看一看其他的源码。加油！！！！
 * <p>
 * 抽象队列同步器 :AbstractQueuedSynchronizer
 * 概总：aqs=state+LCH的队列
 * 默认是调用非公平锁机制
 * 通过模拟案例来学习这个aqs的列子，如果一个线程在工作之后，那么后面进来的线程会被封装成一个node的节点的数据，进入到一个双端队列中。
 * 在队列中。这个维护者也会帮助这个等待的线下去争抢资源。如果抢到了资源，就会删除当前的在队列中的线程。
 * 删除的原理是：将这个抢到资源类的线程变成一个队列的头部节点。原来的节点会指向null最后会别垃圾回收机制回收。
 * 在第一次创建队列的时候。会判断单前是否已经存在了队列，如果没有那就首先会创建一个头节点。然后下一个节点指向第一个进入线程的对象
 */
public class AqsDome {
    public static void main(String[] args) {
        /**
         * 可重入锁的默认的是非公平锁
         *   public ReentrantLock() {
         *         sync = new NonfairSync();
         *     }
         */
        ReentrantLock lock = new ReentrantLock();
        new Thread(() -> {
            lock.lock();
            try {
                System.out.println("-----A thread come in");
                try {
                    TimeUnit.MINUTES.sleep(20);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } finally {
                lock.unlock();
            }
        }, "A").start();
        //第二个顾客，第二个线程---》由于受理业务的窗口只有一个(只能一个线程持有锁)，此时B只能等待，
        new Thread(() -> {
            lock.lock();
            try {
                System.out.println("-----B thread come in");
            } finally {
                lock.unlock();
            }
        }, "B").start();
        //模拟用户来办理业务
        new Thread(() -> {
            lock.lock();
            try {
                System.out.println("-----C thread come in");
            } finally {
                lock.unlock();
            }
        }, "C").start();
    }
}
